#!/usr/bin/python
import re
from subprocess import Popen, PIPE

class aserial(object):
    def __init__(self):
        self.__prefixes = 'kMGTPEZY'
        self.__hdparm = 'hdparm'
        self.__device_re = re.compile(r'[h,s]d[a-z]')
        self.__cache = {}

    def raw_get_info(self, device, template):
        try:
            p = Popen((self.__hdparm, '-I', device), stdout = PIPE, stderr = PIPE)
        except:
            return '-ERR-LAUNCHING-HDPARM-'
        if p.wait() != 0:
            return '-ERR-RUNNING-HDPARM-'
        for line in p.stdout.readlines():
            if line.find('Model Number:') > -1:
                model = line.strip()[13:].strip()
            if line.find('Serial Number:') > -1:
                serial = line.strip()[14:].strip()
            if line.find('LBA') > -1 and line.find('user addressable sectors') > -1:
                lba = int(line.strip().rpartition(' ')[-1])
            if line.find('Logical/Physical Sector size:') > -1:
                ssize = int(line.strip().split(' ')[-2])
        try:
            return template % {'model':model, 'serial':serial, 'size':self.size_str(lba*ssize)}
        except:
            return '-ERR-PARSING-RET-'

    def size_str(self, size):
        prefix_idx = -1
        while size > 1000:
            size /= 1000.0
            prefix_idx += 1
        return '%.1f%s' % (size, self.__prefixes[prefix_idx])

    def get_info(self, device, template = 'Size\'%(size)s\' Model\'%(model)s\' Serial\'%(serial)s\''):
        if len(device) > 5 and device[:5] == '/dev/':
            pass
        else:
            device = '/dev/' + device
        try:
            return self.__cache[device]
        except KeyError:
            info = self.raw_get_info(device, template)
            self.__cache[device] = info
            return info

    def insert(self, line, template = '%(model)s %(serial)s'):
        for device in set(self.__device_re.findall(line)):
            line = line.replace(device, '%s[%s]' % (device, self.get_info(device, template)))
        return line

    def hdtable(self):
        from glob import glob
        for device in sorted(glob('/dev/hd?') + glob('/dev/sd?')):
            yield device + ' ' + self.get_info(device)
            


if __name__ == '__main__':
    ase = aserial()
    import sys
    if len(sys.argv) == 1:
        try:
            for line in sys.stdin.readlines():
                print ase.insert(line),
        except KeyboardInterrupt:
            pass
    elif len(sys.argv) == 2 and sys.argv[1] == '-l':
        for line in ase.hdtable():
            print line

        


